/**
 * @ Author: luoqi
 * @ Create Time: 2024-07-22 21:57
 * @ Modified by: luoqi
 * @ Modified time: 2025-07-11 00:30
 * @ Description:
 */

#include <bsp.h>
#include <stdbool.h>
#include <stdlib.h>
#include "iap/iap.h"
#include "mem/flash.h"
#include "cli.h"

static int _cmd_jmp_hdl(int argc, char **argv)
{
    UNUSED(argv);
    if(argc == 1) {
        iap_jump(IAP_APP_ADDR);
    } else {
        return -1;
    }
    return 0;
}
static int _cmd_iap_hdl(int argc, char **argv)
{
    UNUSED(argv);
    if(argc == 1) {
        bsp_task_suspend("cli");
        bsp_task_resume("iap");
    }
    return 0;
}

static int _cmd_reboot_hdl(int argc, char **argv)
{
    UNUSED(argc);
    UNUSED(argv);
    bsp_reboot();
    return 0;
}

static inline int _iap_send(const void *data, size_t sz)
{
    return bsp_send(data, sz, 100);
}

static inline int _iap_recv(void *data, size_t sz, size_t timeout)
{
    return bsp_recv(data, sz, timeout);
}

static void _jmp_check()
{
    uint8_t c;
    flash_read(IAP_CHECK_ADDR, &c, 1);
    if(c == 0x51) {
        uint8_t flag;
        if(bsp_recv(&flag, 1, 500) == 1) {
            if(flag == 27) { // ESC
                flash_erase(IAP_CHECK_ADDR, 1);
            }
        } else {
            iap_jump(IAP_APP_ADDR);
        }
    }
}

static void _task_cli(void)
{
    uint8_t c;
    if(bsp_recv(&c, 1, 0) == 1) {
        cli_exec(c);
    }
}

static void _task_blink(void)
{
    static bool state = false;
    state = !state;
    if(state) {
        bsp_led_set(LED_LINK, BSP_LED_ON);
    } else {
        bsp_led_set(LED_LINK, BSP_LED_OFF);
    }
}

static void _task_iap()
{
    if(iap_exec() < 0) {
        // BUG: USB receive ringbuffer note read to end
        bsp_blink_set(500, 300);
        bsp_task_suspend("iap");
        bsp_task_resume("cli");
    }
}

int main(void)
{
    bsp_init();

    flash_init();

    iap_init(_iap_send, _iap_recv, flash_write, flash_erase);

    // _jmp_check();

    bsp_task_add("cli", _task_cli, 1);
    bsp_task_add("blink", _task_blink, 1000);
    bsp_task_add("iap", _task_iap, 1);
    bsp_task_suspend("iap");

    cli_add("reboot", _cmd_reboot_hdl, "reboot system");
    cli_add("rb", _cmd_iap_hdl, "ymodem terminal firmware update");
    cli_add("jmp", _cmd_jmp_hdl, "jump to app");

    while(1) {
        bsp_task_exec();
    }

    return 0;
}
